package com.andkrup.web.navigation {
	import com.andkrup.web.navigation.xapi.ExternalEnvironment;	
	import com.andkrup.ds.ICommand;	
	
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;

	/**
	 * This class manages navigation across a sitemap.
	 * 
	 * Register navigator displayobjects that can issue navigational changes.
	 * 
	 * @author Andkrup
	 */
	public class NavigationManager extends EventDispatcher implements INavigationManager, IEventDispatcher {
		private static var _inst:NavigationManager;
		[ArrayElementType("com.andkrup.ds.ICommand")]
		private static var history:Array;
		private static var cursor:uint;
		
		private var navigators : Array;
		private var xApi:ExternalEnvironment;

		public static function get instance():NavigationManager{
			if(!_inst) _inst = new NavigationManager(new NavigationManagerConstructor());
			return _inst;
		}
		
		public function get externalAPI():ExternalEnvironment{
			return xApi;
		}
		public function set externalAPI(value:ExternalEnvironment):void{
			xApi = value;
		}
		
		public function NavigationManager(ctr:NavigationManagerConstructor) {
			super();
			ctr = undefined;
			history = [];
			cursor = 0;
			navigators = [];
		}
		
		/**
		 * This method is the main navigational operation.
		 * 
		 * It takes a ICommand object, invokes its execute() method and stores it
		 * for history and external-interface purposes.
		 */
		public function handleNavigation(command:ICommand):void{
			command.execute();
			history.push(command);
			cursor = history.length;
		}
		public function goto(index:uint):void{
			if(index>history.length){
				return;
			}
			cursor = index;
			var cmd:ICommand = history[cursor] as ICommand;
			cmd.execute();
			if(xApi){
				xApi.call("handleNavigation", cmd);
			}
		}
		public function prev():void{
			if(cursor>0){
				cursor--;
				var cmd:ICommand = history[cursor-1] as ICommand;
				cmd.execute();
				if(xApi){
					xApi.call("prev", cmd);
				}
			}
		}
		public function next():void{
			if(cursor<history.length){
				cursor++;
				var cmd:ICommand = history[cursor-1] as ICommand;
				cmd.execute();
				if(xApi){
					xApi.call("next", cmd);
				}
			}
		}
		
		public function registerNavigator(navigator:Navigator):void{
			unregisterNavigator(navigator);
			navigators.push(navigator);
		}
		public function unregisterNavigator(navigator:Navigator):void{
			var l:int = navigators.length;
			for(var i:int = 0; i < l; i++){
				if(navigator==navigators[i]) navigators.splice(i,1);
			}
		}
	}
}
class NavigationManagerConstructor{}